﻿using System;
using System.Reflection;
using Equation.Enterprise.Framework.Domain.Data;

namespace Equation.Enterprise.Framework.UnitTests
{
    public class DatabaseRepositoryTestBase : IDisposable
    {
        private readonly string _connectionStringName;
        private readonly Assembly[] _mappingAssemblies;
        private static bool _wasInitialized = false;
        private static readonly object LockObject = new Object();
        private readonly IDbContextStorage _storage;

        public DatabaseRepositoryTestBase(string connectionStringName, params Assembly[] mappingAssemblies)
        {
            this._connectionStringName = connectionStringName;
            this._mappingAssemblies = mappingAssemblies;
            this._storage = new SingleContextStorage();
            Setup();
        }

        protected virtual void Setup()
        {
            lock(LockObject)
            {
                if (!_wasInitialized)
                {
                    DbContextManager.Init(this._storage, _connectionStringName, _mappingAssemblies, true);
                    _wasInitialized = true;
                }
            }
        }

        protected virtual void DropAndCreateDatabase(string databaseName)
        {
            if (_wasInitialized)
            {
                if (DbContextManager.Current.Database.Exists())
                {
                    DbContextManager.Current.Database.ExecuteSqlCommand("ALTER DATABASE " + databaseName + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
                    DbContextManager.Current.Database.Delete();
                }
                DbContextManager.Current.Database.Create();
            }
        }

        protected virtual void TearDown()
        {
            DbContextManager.Current.Database.Delete();
        }

        /// <summary>
        /// Reste the current context to create a brand new context
        /// </summary>
        protected virtual void ResetContext()
        {
            if (DbContextManager.Current.Database.Connection.State == System.Data.ConnectionState.Open)
                DbContextManager.Current.Database.Connection.Close();
            this._storage.Context = null;
        }

        private bool _disposed;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        
        private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                //remove managed resources.
                if (disposing)
                {
                    TearDown();
                }
                //remove un-mananges resources
                _disposed = true;
            }
        }
    }
}
